#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>

using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

// 1.异常处理的基本语法
// 2.异常处理的流程〔栈展开
// 3.except关键字
// 4.C+提供的异常类
//     #include <stdexcept>
//     #include <exception>
//《软件调试》 张银奎
// https://isocpp.org/wiki/fag/exceptions
// https://www.yosefk.com/c++fga/exceptions.html
// https://docs.microsoft.com/en-us/cpp/cpp/exception-handling-in-visual-cpp?view=msvc-160

BEGINS(test1)
int main() {
    try {
        cout << "throwing" << endl;
//        throw (1);
        throw string("abc");
        cout << "will not execute" << endl; // unreachable code
    } catch (string &e) {
        cout << "caught an string : " << e << endl;
    }catch (int &e) {
        cout << "caught an integer : " << e << endl;
    }catch (...) { // 捕获任何异常
        cout << "exception caught" << endl;
    }
    cout << "continue from try..." << endl;

    return 0;
}
ENDS(test1)

BEGINS(test2)
class MyException : public runtime_error {
public:
    MyException(const string &s) : runtime_error(s) {
        cout << "MyException ctor" << endl;
    }
    const char *what() const noexcept override {
        // noexcept 不会抛出异常
        // 如果声明了noexcept还是throw的话，程序会直接结束 => double fault
        return "123";
    }
};

int main() {
    try {
        throw (MyException("hello world!"));
    } catch (runtime_error &re) {
        cout << re.what() << endl;
    }

    return 0;
}
ENDS(test2)

BEGINS(test3)

class Helper { // 工具人
public:
    Helper() { cout << "helper ctor" << endl; }
    ~Helper() {cout << "helper dtor" << endl; }
    void boom() { cout << "boom" << endl; }
};

void inner() {
    Helper h[3]; // stack
//    Helper *h = new Helper[3]; // heap
    try {
        throw(1);
    } catch(...) {
        cout << "123" << endl;
    }
    h[0].boom();
}

void outer() {
    try {
        inner();
    } catch (...) {
        cout << "exception caught" << endl;
    }
}

int main() {
    outer();
    return 0;
}

ENDS(test3)

int main() {
//    test1::main();
//    test2::main();
    test3::main();

    return 0;
}